package cz.proks.bank.service;

import java.math.BigDecimal;

import javax.activation.DataHandler;
import javax.jws.WebService;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;

import cz.cvut.felk.support.aos.sw.testadapter.DepositMoneyFault_Exception;
import cz.cvut.felk.support.aos.sw.testadapter.GetAccountStatementFault_Exception;
import cz.cvut.felk.support.aos.sw.testadapter.GetCurrentBalanceFault_Exception;
import cz.cvut.felk.support.aos.sw.testadapter.SetUpAccountFault_Exception;
import cz.cvut.felk.support.aos.sw.testadapter.TransferMoneyFault_Exception;
import cz.cvut.felk.support.aos.sw.testadapter.WithdrawMoneyFault_Exception;
import cz.proks.bank.BankConstants;
import cz.proks.bank.domain.Account;
import cz.proks.bank.domain.Loan;
import cz.proks.bank.manager.AccountManager;
import cz.proks.bank.manager.LoanManager;
import cz.proks.bank.manager.exeception.BankException;
import cz.proks.bank.manager.exeception.LoanRejectedException;
import cz.proks.bank.service.exception.LoanException;

@WebService(endpointInterface = "cz.proks.bank.service.ClientService", 
			serviceName = "ClientService",
			portName = "ClientServicePort",
			targetNamespace = "http://bank.proks.cz/service/ClientService/")
public class ClientServiceImpl implements ClientService {
	private final Logger log = Logger.getLogger(getClass());
	
	@Autowired
	private AccountManager accountManager;
	
	@Autowired
	private LoanManager loanManager;
	
	@Override
	public BigDecimal depositMoney(int accountNumber, BigDecimal amount, String currency) throws DepositMoneyFault_Exception {
		try {
			return new BigDecimal(accountManager.depositMoney(accountNumber, currency, amount.intValue()));
		} catch (BankException e) {
			log.error("", e);
			throw new DepositMoneyFault_Exception();
		}		
	}

	@Override
	public int setUpAccount(String name, String currency) throws SetUpAccountFault_Exception {
		Account account = accountManager.createAccount(BankConstants.BANK_CODE, name, currency);
		return account.getId();
	}

	@Override
	public BigDecimal getCurrentBalance(int accountNumber, String currency)	throws GetCurrentBalanceFault_Exception {
		try {
			return new BigDecimal(accountManager.getAvalilableMoney(accountNumber, currency));
		} catch (BankException e) {
			log.error("", e);
			throw new GetCurrentBalanceFault_Exception();			
		}
	}

	@Override
	public BigDecimal withdrawMoney(int accountNumber, BigDecimal amount, String currency) throws WithdrawMoneyFault_Exception {
		try {
			return new BigDecimal(accountManager.withdrawMoney(accountNumber, currency, amount.intValue()));
		} catch (BankException e) {
			log.error("", e);
			throw new WithdrawMoneyFault_Exception();
		}	
	}

	@Override
	public DataHandler getAccountStatement(int accountNumber) throws GetAccountStatementFault_Exception {
		try {
			return accountManager.getAccountReport(accountNumber);
		} catch (Exception e) {
			log.error("", e);
			throw new GetAccountStatementFault_Exception();
		}		
	}

	@Override
	public void transferMoney(int sourceAccount, int targetAccount, String targetBank, BigDecimal amount, String currency) throws TransferMoneyFault_Exception {
		try {
			accountManager.transferMoney(sourceAccount, targetAccount, targetBank, amount.intValue(), currency);
		} catch (BankException e) {
			log.error("", e);
			throw new TransferMoneyFault_Exception();
		}		
	}

	@Override
	public long requestForLoan(int accountNumber, long amount, String currency)	throws LoanException {
		try {
			Loan loan = loanManager.createLoan(accountNumber, amount, currency);
			return loan.getId();
		} catch (LoanRejectedException e) {
			throw new LoanException();
		}
	}

	@Override
	public long insertRepayment(long loanId, long repaymentAmount, String currency) throws LoanException {
		try {
			Loan loan = loanManager.insertRepayment(loanId, repaymentAmount, currency);
			return loan.getRemainingAmount();
		} catch (cz.proks.bank.manager.exeception.LoanException e) {
			throw new LoanException();
		}
		
	}	
}
